package com.fastdfs.controller;

import com.fastdfs.pojo.Album;
import com.fastdfs.pojo.AlbumImageitems;
import com.fastdfs.pojo.FastDFSPojo;
import com.fastdfs.pojo.Imageitems;
import com.fastdfs.service.AlbumImageitemsService;
import com.fastdfs.service.AlbumService;
import com.fastdfs.service.ImageitemsService;
import com.fastdfs.util.*;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@RestController
@RequestMapping("/album")
@CrossOrigin  //开启跨域
public class AlbumController {


    @Autowired
    private AlbumService albumService;
    @Autowired
    private AlbumImageitemsService albumImageitemsService;
    @Autowired
    private ImageitemsService imageitemsService;



    /***
     *  文件上传  单张
     * @param  file  表单的name
     * @param   image_describe  图片描述  (可有可无)
     * @return  返回文件地址
     */
    @PostMapping(value = "/upload")
    public Result<Imageitems> upload(@RequestParam("file") MultipartFile file,String image_describe) throws Exception {
        if (file==null||file.isEmpty()){
            return new Result<Imageitems>(false, StatusCode.OK,"空文件?",null);
        }

        //封装一个FastDFSFile
        FastDFSPojo fastDFSFile = new FastDFSPojo(
                file.getOriginalFilename(), //文件名字
                file.getBytes(),            //文件字节数组
                StringUtils.getFilenameExtension(file.getOriginalFilename()));//文件扩展名

        String s=null;
        //文件上传
        String[] uploads = FastDFSClient.upload(fastDFSFile);
        if(FastDFSPojo.vip_ip!=null){
            s = FastDFSClient.getTrackerUrl(FastDFSPojo.vip_ip) + "/" + uploads[0] + "/" + uploads[1];  //拼接结果
        }else {
            s = FastDFSClient.getTrackerUrl() + "/" + uploads[0] + "/" + uploads[1];  //拼接结果
        }

        ImageUtils imageUtils =new ImageUtils();
        imageUtils.readPic(s,true);



        Imageitems imageitems=new Imageitems();
        imageitems.setId( Id_Builder.nextId());
        String substring = uploads[1].substring(uploads[1].lastIndexOf("/") + 1, uploads[1].length());
        imageitems.setName(substring);
        imageitems.setImagePath(uploads[1]);
        imageitems.setImage(s);
        imageitems.setImageGroup(uploads[0]);
        imageitems.setImageDescribe(image_describe);
        imageitems.setImageType( imageUtils.getType());
        imageitems.setImageSize(imageUtils.getSize());
        imageitems.setImagePx(imageUtils.getWidth()+"*"+imageUtils.getHeight());
        imageitems.setImageData(DateUtils.dateStrng());

        imageitemsService.add(imageitems);
        //组装文件上传地址
        return new Result<Imageitems>(true, StatusCode.OK,"文件上传成功",imageitems ) ;

    }


    /***
     *  文件上传  多张图片
     * @param  file  表单的name
     * @param   image_describe  图片描述  (可有可无)
     * @return  返回文件地址
     */
    @PostMapping(value = "/uploads")
    public Result<List<Result<Imageitems>>>   uploads(@RequestParam("file") MultipartFile[] file,String[] image_describe) throws Exception {
        if (file==null||file.length==0){
           return new Result<List<Result<Imageitems>>>(false,StatusCode.OK,"文件上传失败",null);
        }




        List<Result> results=new ArrayList<>();
        for (int i = 0; i < file.length; i++) {


            //封装一个FastDFSFile
            FastDFSPojo fastDFSFile = new FastDFSPojo(
                    file[i].getOriginalFilename(), //文件名字
                    file[i].getBytes(),            //文件字节数组
                    StringUtils.getFilenameExtension(file[i].getOriginalFilename()));//文件扩展名

            String s=null;
            //文件上传
            String[] uploads = FastDFSClient.upload(fastDFSFile);
            if(FastDFSPojo.vip_ip!=null){
                s = FastDFSClient.getTrackerUrl(FastDFSPojo.vip_ip) + "/" + uploads[0] + "/" + uploads[1];  //拼接结果
            }else {
                s = FastDFSClient.getTrackerUrl() + "/" + uploads[0] + "/" + uploads[1];  //拼接结果
            }

            ImageUtils imageUtils =new ImageUtils();
            imageUtils.readPic(s,true);

            Imageitems imageitems=new Imageitems();

            imageitems.setId( Id_Builder.nextId());
            String substring = uploads[1].substring(uploads[1].lastIndexOf("/") + 1, uploads[1].length());
            imageitems.setName(substring);
            imageitems.setImagePath(uploads[1]);
            imageitems.setImage(s);
            imageitems.setImageGroup(uploads[0]);
            if(image_describe!=null){
                imageitems.setImageDescribe(image_describe[i]);
            }
            imageitems.setImageType( imageUtils.getType());
            imageitems.setImageSize(imageUtils.getSize());
            imageitems.setImagePx(imageUtils.getWidth()+"*"+imageUtils.getHeight());
            imageitems.setImageData(DateUtils.dateStrng());
            imageitemsService.add(imageitems);
            //组装文件上传地址
            results.add(new Result<Imageitems>(true, StatusCode.OK,uploads[1]+"文件上传成功",imageitems ) ); ;
        }

        return new Result<List<Result<Imageitems>>>(true,StatusCode.OK,"文件上传成功",results);

    }




    /***
     * 通过图片id 下载  (单个下载)
     * @param id  图片id
     *
     * @return
     */
    @GetMapping(value = "/downFile/{id}")
    public  void downFile(@PathVariable  String id, HttpServletResponse response){
        response.setContentType("application/x-download");//设置为下载application/x-download
        Imageitems  image = imageitemsService.findById(id);
        try {
        String filedisplay = image.getImagePath();//下载文件时显示的文件保存名称
        String filenamedisplay = URLEncoder.encode(filedisplay,"UTF-8"); //将文件名进行转义 防止中文名称不显示导致文件错误
        response.addHeader("Content-Disposition","attachment;filename=" + filenamedisplay);//展示给用户的
        byte[] bytes = FastDFSClient.downFile(image.getImageGroup(), image.getName());
        ServletOutputStream outputStream = null;
            outputStream = response.getOutputStream();
        //将字节数组转换成字节输入流
            outputStream.write(bytes,0,bytes.length);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }




    /***
     * 批量图片压缩zip 然后 下载   (简称批量下载)
     * @param id  图片id
     *
     * @return
     */
    @GetMapping(value = "/downFiles")
    public void downloadZipFile( String[] id,HttpServletResponse response) throws IOException {
        byte[] bytes1=null;
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ZipOutputStream zip = new ZipOutputStream(outputStream);
        int i=0;
        for (String aString : id) {
            Imageitems  image = imageitemsService.findById(aString);
            byte[] bytes = FastDFSClient.downFile(image.getImageGroup(), image.getImagePath());
            //添加到zip,一定要加目录
            zip.putNextEntry(new ZipEntry( i+image.getName()));
                    IOUtils.write(bytes, zip);
            i++;
            zip.closeEntry();
        }
        IOUtils.closeQuietly(zip);

        byte[] data = outputStream.toByteArray();

        response.reset();
        response.setContentType("application/octet-stream; charset=UTF-8");
        response.setHeader("Content-Disposition", "attachment;filename="+ new String(("image" + ".zip").getBytes(), "UTF-8"));

        IOUtils.write(data, response.getOutputStream());
    }



    /***
     * 根据ID删除相册和相册内的图片  (关联删除)
     * @param id
     * @return
     */
    @DeleteMapping(value = "/albunDe/{id}" )
    public Result delete(@PathVariable String id, @RequestBody String path) throws Exception {


        String urlDecode= URLDecoder.decode(path);
        String str=urlDecode;
        System.out.println(str);
        int m00 = str.indexOf("M00");
        String substring = str.substring(m00, str.length());

        int group = str.indexOf("group");
        String substring1 = str.substring( group, m00-1 );

        Map<String,Object>  mp=new HashMap();
        mp.put("group",substring1);
        mp.put("fileName",substring);
         // 删除相册封面 的物理图片
        String s = HttpUtils.doDelete("http://localhost:20210/album/deleteFile", mp);
        System.out.println(s);
        Map<String, Object> turn = JsonTurnUtils.jsonTurnMap(s);
        if( (Boolean) turn.get("flag") ){
            albumService.delete(id);  //相册删除成功
            //删除子相册内容
            AlbumImageitems albumImageitems=new AlbumImageitems();
            albumImageitems.setAlbumId(id);
            albumImageitemsService.delete(albumImageitems);

            //更新缓存
            try {
                String albumAll = RedisUtis.getStringRedis("albumAll");
                if(NullUtils.notEmpty( albumAll)){
                    List<Album> objects = JsonTurnUtils.jsonTurnList(albumAll, Album.class);
                    for (int i = 0; i < objects.size(); i++) {
                        if(objects.get(i).getId().equals(id)){
                            System.out.println("找到了要删除的相册缓存");
                            objects.remove(i);
                        }
                    }

                    RedisUtis.setStringRedis("albumAll",objects);
                    System.out.println("根据ID删除相册和相册内的图片 ---更新缓存成功");
                }

            } catch (Exception e) {
                e.printStackTrace();

                System.out.println("根据ID删除相册和相册内的图片 ---更新缓存失败");
                return new Result(false, StatusCode.OK,"添加失败-缓存问题");
            }

            return new Result(true,StatusCode.OK,"删除成功");
        }else {
            return new Result(false,StatusCode.ERROR,"删除失败");
        }




    }



    /***
     * 修改Album数据
     * @param album
     * @param id
     * @return
     */
    @PutMapping(value="/up/{id}")
    public Result update(@RequestParam(value = "file" ,required = false) MultipartFile file, Album album,@PathVariable String id) throws Exception {

        if(NullUtils.notEmpty(album)){
            Album a=new Album();
            a.setTitle(album.getTitle());
            int i =  albumService.selectCount(a);
            if (i >=1){
                return new Result(false, StatusCode.OK,"添加失败-有此相册类型了");
            }
        }

        if(file!=null&&!file.isEmpty()){

            Imageitems imageitems = new Imageitems();
            imageitems.setImage(album.getImage());
            //删除仓库里 原来的封面图片
            int i = imageitemsService.deleteCondition(imageitems);
            if(i<1){
                throw new  Exception("封面原图片删除失败");
            }
            //把相册新的封面图片存 储到图片仓库里
            Result<Imageitems> upload = upload(file, album.getImageDescribe());
            Imageitems data= upload.getData();
            album.setImage(data.getImage());    //图片可访问url
        }

        //设置主键值
        album.setId(id);
        //修改数据
        albumService.update(album);

        //更新缓存
        try {
            String albumAll = RedisUtis.getStringRedis("albumAll");
            if(NullUtils.notEmpty( albumAll)){
                List<Album> objects = JsonTurnUtils.jsonTurnList(albumAll, Album.class);
                for (Album object : objects) {
                    if(object.getId().equals(id)){
                        System.out.println("找到了要更新的相册缓存");
                        object.setTitle(album.getTitle());
                        object.setImage(album.getImage());
                        object.setImageDescribe(album.getImageDescribe());
                        //修改里的缓存
                        RedisUtis.setStringRedis("albumAll"+id,object);  //设置缓存
                    }

                }
                //整个相册的缓存
                RedisUtis.setStringRedis("albumAll",objects);

                System.out.println("修改Album数据----更新缓存成功");
            }

        } catch (Exception e) {
            e.printStackTrace();

            System.out.println("新增Album数据 ---更新缓存失败");
            return new Result(false, StatusCode.OK,"更新失败-缓存问题");
        }


        return new Result(true,StatusCode.OK,"修改成功");



    }

    /***
     * 新增Album数据
     * @param album
     * @return
     */
    @PostMapping
    public Result add(@RequestParam("file") MultipartFile file,Album album) throws Exception {

        Album a=new Album();
        a.setTitle(album.getTitle());
        int i =  albumService.selectCount(a);
        if (i >=1){
            return new Result(false, StatusCode.OK,"添加失败-有此相册类型了");
        }
        //把相册封面图片存 储到图片仓库里
        Result<Imageitems> upload = upload(file, null);
        Imageitems data = upload.getData();

        album.setId(Id_Builder.nextId());
        album.setImage(data.getImage());    //图片可访问url
        album.setImageData(DateUtils.dateStrng()); //创建此相册的时间
        albumService.add(album);

        //更新缓存
        try {
            String albumAll = RedisUtis.getStringRedis("albumAll");
            if(NullUtils.notEmpty( albumAll)){
                List<Album> objects = JsonTurnUtils.jsonTurnList(albumAll, Album.class);
                objects.add(album);
                RedisUtis.setStringRedis("albumAll",objects);
                System.out.println("新增Album数据----更新缓存成功");
            }


        } catch (Exception e) {
            e.printStackTrace();

            System.out.println("新增Album数据 ---更新缓存失败");
            return new Result(false, StatusCode.OK,"添加失败-缓存问题");
        }

        return new Result(true, StatusCode.OK,"添加成功");
    }




    /***
     * 根据ID查询Album数据
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public Result<Album> findById(@PathVariable String id){
        String albumAll = RedisUtis.getStringRedis("albumAll"+id);
        if(NullUtils.notEmpty( albumAll)){
            Album album =JsonTurnUtils.jsonTurnJavaBena(albumAll,Album.class);
                    System.out.println("根据ID查询Album数据----缓存");
                    return new Result<Album>(true,StatusCode.OK,"查询成功",album);
        }

        //根据ID查询
        Album album = albumService.findById(id);

        if (album==null){
            return  new Result<Album>(false,StatusCode.OK,"查询失败",album);
        }
        RedisUtis.setStringRedis("albumAll"+id,album);  //设置缓存

        return new Result<Album>(true,StatusCode.OK,"查询成功",album);
    }


    /***
     * 查询Album全部数据
     * @return
     */
    @GetMapping
    public Result<Album> findAll(){


        //读取缓存
        String albumAll = RedisUtis.getStringRedis("albumAll");
        if (NullUtils.notEmpty(albumAll)){
            System.out.println("查询Album全部数据---调用缓存");
            System.out.println(albumAll);
            return new Result<Album>(true, StatusCode.OK,"查询成功",JsonTurnUtils.jsonTurnList(albumAll,Album.class)) ;
        }

        List<Album> list=albumService.findAll();

        // 判断图片 是否是 可访问的  如果图片不可访问那么 删除不可访问的路径
        for (int i = 0; i < list.size(); i++) {
            String image = list.get(i).getImage();
            boolean b = ImageUtils.existRource(image);
            if (!b){
                list.remove(i);
                System.out.println("访问不了"+image);
            }
        }
        //设置缓存
        System.out.println("查询Album全部数据---设置缓存");
        RedisUtis.setStringRedis("albumAll",list);
        System.out.println(list);
        return new Result<Album>(true, StatusCode.OK,"查询成功",list) ;
    }

    /***
     * 文件删除实现 (仓库 物理删除)
     * @param  body
     */
    @DeleteMapping(value = "/deleteFile")
    public static Result deleteFile(@RequestBody String body){
        System.out.println("物理删除");
        System.out.println("要删除的数据"+body);
        Map<String, Object> turn = JsonTurnUtils.jsonTurnMap(body);

        try {
            FastDFSClient.deleteFile((String) turn.get("group"),(String) turn.get("fileName"));
        } catch (Exception e) {
            e.printStackTrace();
            return new Result(false,StatusCode.ERROR,"仓库文件删除失败");
        }
        return new Result(true,StatusCode.OK,"仓库文件删除成功");
    }


}